#! /usr/bin/python3

import os
import sys
import subprocess
import json
import openpyxl
import xlwt

def run_cmd(cmd):
    res = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)
    sout, serr = res.communicate()

    return res.pid, res.returncode, sout, serr

def write_raw_data(workbook, duration_table):
    worksheet = workbook.create_sheet()
    worksheet.title = "raw-data"
    line_number = 0
    for data in duration_table:
        line_number += 1
        worksheet.cell(line_number, 1, data[0])
        worksheet.cell(line_number, 2, data[1])

def write_summary(workbook, out_dict):
    worksheet = workbook.active
    worksheet.title = "summary"
    worksheet.cell(1, 1, "module")
    worksheet.cell(1, 2, "total duration(ms)")
    line_number = 1
    summary_dict = {}
    for key, value in out_dict.items():
        total_duration = 0
        for name, dur in out_dict[key].items():
            total_duration += dur
        summary_dict[key] = total_duration
    summary_sorted_dict = sorted(summary_dict.items(), key=lambda x:x[1],reverse=True)
    for key, value in summary_sorted_dict:
        line_number += 1
        worksheet.cell(line_number, 1, key)
        worksheet.cell(line_number, 2, value)

def write_top(workbook, duration_table, default_top_limit = 50):
    worksheet = workbook.create_sheet()
    worksheet.title = "top-" + str(default_top_limit)
    lines_limit = min(len(duration_table), default_top_limit)
    line_number = 0
    for data in duration_table:
        if "unstripped" in data[0]:
            continue
        else:
            line_number += 1
            if (line_number > lines_limit):
                break
            worksheet.cell(line_number, 1, duration_table[line_number][0])
            worksheet.cell(line_number, 2, duration_table[line_number][1])

def write_uncatched(workbook, no_catch_dict):
    worksheet = workbook.create_sheet()
    worksheet.title = "uncatch-list"
    worksheet.cell(1, 1, "obj")
    worksheet.cell(1, 2, "duration(ms)")
    line_number = 1
    for key, value in no_catch_dict.items():
        line_number += 1
        worksheet.cell(line_number, 1, key)
        worksheet.cell(line_number, 2, value)

def write_module(workbook, out_dict):
    for key, value in out_dict.items():
        worksheet = workbook.create_sheet()
        sheet_name = key.replace("/", "-")
        worksheet.title = sheet_name
        worksheet.cell(1, 1, "obj")
        worksheet.cell(1, 2, "duration(ms)")
        line_number = 1
        for key1, value1 in out_dict[key].items():
            line_number += 1
            worksheet.cell(line_number, 1, key1)
            worksheet.cell(line_number, 2, value1)

def write_to_excel(duration_table, pattern_name_list, no_catch_dict, out_dict):
    workbook = openpyxl.Workbook()
    write_summary(workbook, out_dict)
    write_top(workbook, duration_table, 60)
    write_uncatched(workbook, no_catch_dict)
    write_raw_data(workbook, duration_table)
    write_module(workbook, out_dict)
    workbook.save(filename="ninja-log-parse.xlsx")

def parse_ninja_log(ninja_log):
    global_table = {}
    skip_first_line = True
    with open(ninja_log) as f:
        for line in f.readlines():
            if (skip_first_line):
                skip_first_line = False
                continue
            st_time = line.split()[0]
            end_time = line.split()[1]
            obj_name = line.split()[3]
            duration = float(end_time) - float(st_time)
            global_table[obj_name] = duration
    sorted_table = sorted(global_table.items(), key=lambda x:x[1],reverse=True)
    return sorted_table

def statistic_duration(duration_table, pattern_name_list):
    inclusiv_list = {
        "drivers/hdf_core":["hdf_core"],
        "third_party":["thirdparty"],
        "ark/js_runtime": ["js_runtime", "libark", "clang_x64/ark/ark/build", "stub.m", "arkXtest", "js_runtime"],
        "base/telephony":["telephony"],
        "base/miscservices":["miscservices"],
        "base/hiviewdfx":["hiviewdfx"],
    }
    total_sample = 0
    total_time = 0
    catch_sample = 0
    catch_time = 0
    no_catch_dict = {}
    out_dict = {}
    for data in duration_table:
        print(data[0])
        catch_flag = False
        total_sample += 1
        total_time += data[1]
        for p in pattern_name_list:
            if p in data[0]:
                print(p)
                catch_sample += 1
                catch_time += data[1]
                if p not in out_dict.keys():
                    out_dict[p] ={}
                out_dict[p][data[0]] = data[1]
                catch_flag = True
                break
            elif p in inclusiv_list.keys():
                for p1 in inclusiv_list[p]:
                    if p1 in data[0]:
                        catch_sample += 1
                        catch_time += data[1]
                        if p not in out_dict.keys():
                            out_dict[p] ={}
                        out_dict[p][data[0]] = data[1]
                        catch_flag = True
                        break
            else:
                continue               
        if not catch_flag:
            no_catch_dict[data[0]] = data[1]
    print("--------Sumamry-----------")
    print("total sample: " + str(total_sample) + ", " + "catch sample: " + str(catch_sample) + ", pct: " + str(round(catch_sample / total_sample * 100, 2)) + "%")
    print("total time: " + str(total_time) + ", " + "catch time: " + str(catch_time) + ", pct: " + str(round(catch_time / total_time *100, 2)) + "%")
    # for key, value in no_catch_dict.items():
    #     print(key + ", " + str(value))
    return out_dict, no_catch_dict

def get_partten(oh_dir):
    pattern_name_list = []
    first_level_dir = []
    remove_dirs = ["prebuilts", "productdefine", "docs", "out", "ccache-debug-dir", "vendor", "build", "third_party"]
    for home, dirs, files in os.walk(oh_dir):
        for d in dirs:
            if d[0] != "." and d not in remove_dirs:
                first_level_dir.append(d)
        break
    
    for d1 in first_level_dir:
        if (d1 == "applications"):
            # print(d1 + "/" + d2)
            pattern_name_list.append(d1)
            continue
        for home, dirs, files in os.walk(os.path.join(oh_dir, d1)):
            for d2 in dirs:
                if d2 == "ai":
                    continue
                if (d2 == "arkXtest"):
                    continue
                if (d1 == "foundation"):
                    # print(d1 + "/" + d2)
                    pattern_name_list.append(d2)
                if (d1 == "base" and d2 == "security"):
                    pattern_name_list.append(d2 + "/")
                else:
                    pattern_name_list.append(d1 + "/" + d2)
            break
    pattern_name_list.append("third_party")
    pattern_name_list.append("hdf/")
    return pattern_name_list

def write_to_json(out_dict):
    with open("ninja-log-parse.json","w") as f:
        json.dump(out_dict,f)

def main():
    oh_dir = "/home/yinchuang/Code/OH/"
    pattern_name_list = get_partten(oh_dir)
    print(pattern_name_list)
    duration_table = parse_ninja_log("ninja_log")
    out_dict, no_catch_dict= statistic_duration(duration_table, pattern_name_list)
    write_to_json(out_dict)
    write_to_excel(duration_table, pattern_name_list, no_catch_dict, out_dict)

if __name__ == '__main__':
    main()